﻿using System.Collections.Generic;
using NLog;
using Roslyn.Compilers.CSharp;

namespace TfsGiggle.Core.Parsers
{
    /// <summary>
    /// Provides parsing of C# files
    /// </summary>
    class RoslynCSharpParser : SyntaxWalker, IParser
    {
        static LoggerWithEventId _logger = (LoggerWithEventId)LogManager.GetCurrentClassLogger(typeof(LoggerWithEventId));
        List<string> _usingDeclarations = new List<string>();
        List<string> _classDeclarations = new List<string>();
        List<string> _interfaceDeclarations = new List<string>();
        List<string> _methodDeclarations = new List<string>();

        /// <summary>
        /// Parses the content in sourceCodeContent
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="sourceCodeContent"></param>
        public void Parse(string fileName, string sourceCodeContent)
        {
            _logger.Trace("enter '{0}'", fileName);
            var tree = SyntaxTree.ParseCompilationUnit(sourceCodeContent);
            this.Visit(tree.Root);
            _logger.Trace("exit");
        }

        /// <summary>
        /// Classes
        /// </summary>
        /// <param name="node"></param>
        protected override void VisitClassDeclaration(ClassDeclarationSyntax node)
        {
            if (!_classDeclarations.Contains(node.Identifier.ValueText))
            {
                _classDeclarations.Add(node.Identifier.ValueText);
            }

            // Let the visitation continue
            base.VisitClassDeclaration(node);
        }

        /// <summary>
        /// Methods
        /// </summary>
        /// <param name="node"></param>
        protected override void VisitMethodDeclaration(MethodDeclarationSyntax node)
        {
            if (!_methodDeclarations.Contains(node.Identifier.ValueText))
            {
                _methodDeclarations.Add(node.Identifier.ValueText);
            }

            // Let the visitation continue
            base.VisitMethodDeclaration(node);
        }

        /// <summary>
        /// Interfaces
        /// </summary>
        /// <param name="node"></param>
        protected override void VisitInterfaceDeclaration(InterfaceDeclarationSyntax node)
        {
            if (!_interfaceDeclarations.Contains(node.Identifier.ValueText))
            {
                _interfaceDeclarations.Add(node.Identifier.ValueText);
            }

            // Let the visitation continue
            base.VisitInterfaceDeclaration(node);
        }

        /// <summary>
        /// Usings
        /// </summary>
        /// <param name="node"></param>
        protected override void VisitUsingDirective(UsingDirectiveSyntax node)
        {
            if (!_usingDeclarations.Contains(node.Name.PlainName))
            {
                _usingDeclarations.Add(node.Name.PlainName);
            }

            // Let the visitation continue
            base.VisitUsingDirective(node);
        }

        /// <summary>
        /// Usings
        /// </summary>
        public List<string> UsingDeclarations { get { return _usingDeclarations; } }

        /// <summary>
        /// Classes
        /// </summary>
        public List<string> ClassDeclarations { get { return _classDeclarations; } }

        /// <summary>
        /// Interfaces
        /// </summary>
        public List<string> InterfaceDeclarations { get { return _interfaceDeclarations; } }

        /// <summary>
        /// Methods
        /// </summary>
        public List<string> MethodDeclarations { get { return _methodDeclarations; } }

        /// <summary>
        /// Name
        /// </summary>
        public string Name
        {
            get
            {
                return "CSharpRoslyn";
            }
        }
    }
}
